package com.noahsloan.groovy.algorithms

/**
 * @author noah
 *
 */
public class TestGraphBuilder extends GroovyTestCase{
	
	GraphBuilder builder
	
	void setUp() {
		builder = new GraphBuilder()
		builder.node("a") {
			node("b") {
				edge("d") // edge to node that doesn't exist yet
			}
			node(foo:'bar',baz:2,"c") // node with attributes
			node("d") {
				node("f")
				edge("b") { foo("bar") } // forward edge
				node("e")
			}			
		}
		builder.node("g") {
			node("h")
			edge("c") // cross edge
			node("i") {
				node("j")
				edge("j") // duplicate edge
				node("k") { edge("i") } // edge back to parent
			}
			node(data:"l",foo:'foo') // attributes only (data required)
		}
		builder.node(foo:123,"f") // node augmentation
	}
	
	void testNodeCreation() {
		def nodes = builder.nodes.values()
		('a'..'l').each { id ->
			assertTrue("node $id not created",nodes.any { n -> n.data == id })
		}
		
		def f = nodes.find { it.data == 'f' }
		assertNotNull("f",f)
		assertEquals("f not augmented properly",123,f.foo)
		
		def c = nodes.find { it.data == 'c' }
		assertNotNull("c",f)
		assertEquals("c.foo",'bar',c.foo)
		assertEquals("c.baz",2,c.baz)
		
		def l = nodes.find { it.data == 'l' }
		assertNotNull("l",f)
		assertEquals("l.foo",'foo',l.foo)
	}
	
	void testEdgeCreation() {
		def result = builder.edges
		def edges = [['a','b'],['b','d'],['a','c'],['a','d'],['d','f'],
			         ['d','b'],['d','e'],['g','h'],['g','c'],['g','i'],
			         ['i','j'],['i','k'],['k','i'],['g','l']]
		edges.each { e ->
			assertTrue("$e", result.any { it.start.data == e[0] && it.end.data == e[1] })
		}
		assertEquals(edges.size(),result.size())
		assertEquals("bar",result.find { it.start.data == 'd' && it.end.data == 'b' }.foo)
	}
	
	void testConnections() {
		def paths = [
         ['a','b','d','e'],
         ['g','c'],
         ['g','i','k','i','j']
        ]
		paths.each { path ->
			def current = builder.nodes.values().find { it.data == path[0] }
			path[1..-1].eachWithIndex { next, i -> 
				assertNotNull("Missing edge ${path[i]} -> ${next}",
						current = current.outgoing.find { it.end.data == next }?.end)
			}
		}
	}
}
